\subsubsection{GCC}

Теперь скомпилируем то же самое компилятором GCC 4.4.1 в Linux: \TT{gcc 1.c -o 1}.
Затем при помощи \IDA посмотрим как скомпилировалась функция \main.
\IDA, как и MSVC, показывает код в синтаксисе Intel\footnote{Мы также можем заставить GCC генерировать листинги в этом формате при помощи ключей \TT{-S -masm=intel}.}.

\begin{lstlisting}[caption=код в \IDA,style=customasmx86]
main            proc near

var_10          = dword ptr -10h

                push    ebp
                mov     ebp, esp
                and     esp, 0FFFFFFF0h
                sub     esp, 10h
                mov     eax, offset aHelloWorld ; "hello, world\n"
                mov     [esp+10h+var_10], eax
                call    _printf
                mov     eax, 0
                leave
                retn
main            endp
\end{lstlisting}

\myindex{Function prologue}
\myindex{x86!\Instructions!AND}
Почти то же самое. 
Адрес строки \TT{hello, world}, лежащей в сегменте данных, вначале сохраняется в \EAX, затем записывается в стек.
А ещё в прологе функции мы видим \TT{AND ESP, 0FFFFFFF0h}~--- 
эта инструкция выравнивает значение в \ESP по 16-байтной границе, делая все значения 
в стеке также выровненными по этой границе (процессор более эффективно работает с переменными, расположенными
в памяти по адресам кратным 4 или 16)\footnote{\URLWPDA}.

\myindex{x86!\Instructions!SUB}
\INS{SUB ESP, 10h} выделяет в стеке 16 байт. Хотя, как будет видно далее, здесь достаточно только 4.

Это происходит потому, что количество выделяемого места в локальном стеке тоже выровнено по 16-байтной границе.

% TODO1: rewrite.
\myindex{x86!\Instructions!PUSH}
Адрес строки (или указатель на строку) затем записывается прямо в стек без помощи инструкции \PUSH.
\IT{var\_10} одновременно и локальная переменная и аргумент для \printf{}. Подробнее об этом будет ниже.

Затем вызывается \printf.

В отличие от MSVC, GCC в компиляции без включенной оптимизации генерирует \TT{MOV EAX, 0} вместо более короткого опкода.

\myindex{x86!\Instructions!LEAVE}
Последняя инструкция \LEAVE~--- это аналог команд \TT{MOV ESP, EBP} и \TT{POP EBP}~--- то есть возврат \glslink{stack pointer}{указателя стека} и регистра \EBP в первоначальное состояние.
Это необходимо, т.к. в начале функции мы модифицировали регистры \ESP и \EBP{}\\
(при помощи \INS{MOV EBP, ESP} / \INS{AND ESP, \ldots}).

\subsubsection{GCC: \ATTSyntax}
\label{ATT_syntax}

Попробуем посмотреть, как выглядит то же самое в синтаксисе AT\&T языка ассемблера.
Этот синтаксис больше распространен в UNIX-мире.

\begin{lstlisting}[caption=компилируем в GCC 4.7.3]
gcc -S 1_1.c
\end{lstlisting}

Получим такой файл:

\lstinputlisting[caption=GCC 4.7.3,style=customasmx86]{patterns/01_helloworld/GCC.s}

Здесь много макросов (начинающихся с точки). Они нам пока не интересны.

Пока что, ради упрощения, мы можем 
их игнорировать (кроме макроса \IT{.string}, при помощи которого кодируется последовательность символов, 
оканчивающихся нулем~--- такие же строки как в Си). И тогда получится следующее
\footnote{Кстати, для уменьшения генерации \q{лишних} макросов, можно использовать такой ключ GCC: \IT{-fno-asynchronous-unwind-tables}}:

\lstinputlisting[caption=GCC 4.7.3,style=customasmx86]{patterns/01_helloworld/GCC_refined.s}

\myindex{\ATTSyntax}
\myindex{\IntelSyntax}
Основные отличия синтаксиса Intel и AT\&T следующие:

\begin{itemize}

\item
Операнды записываются наоборот.

В Intel-синтаксисе: \\
<инструкция> <операнд назначения> <операнд-источник>.

В AT\&T-синтаксисе: \\
<инструкция> <операнд-источник> <операнд назначения>.

\myindex{\CStandardLibrary!memcpy()}
\myindex{\CStandardLibrary!strcpy()}
Чтобы легче понимать разницу, можно запомнить следующее:
когда вы работаете с синтаксисом Intel~--- можете в уме ставить знак равенства ($=$) между операндами,
а когда с синтаксисом AT\&T~--- мысленно ставьте стрелку направо ($\rightarrow$)
\footnote{Кстати, в некоторых стандартных функциях библиотеки Си (например, memcpy(), strcpy()) также применяется 
расстановка аргументов как в синтаксисе Intel: вначале указатель в памяти на блок назначения, 
затем указатель на блок-источник.}.

\item
AT\&T: Перед именами регистров ставится символ процента (\%), а перед числами символ доллара (\$).
Вместо квадратных скобок используются круглые.

\item
AT\&T: К каждой инструкции добавляется специальный символ, определяющий тип данных:

\begin{itemize}
\item q --- quad (64 бита)
\item l --- long (32 бита)
\item w --- word (16 бит)
\item b --- byte (8 бит)
\end{itemize}

% TODO1 simple example may be? \RU{Например mov\textbf{l}, movb, movw представляют различые версии инсструкция mov} \EN {For example: movl, movb, movw are variations of the mov instruciton}

\end{itemize}

Возвращаясь к результату компиляции: он идентичен тому, который мы посмотрели в \IDA.
Одна мелочь: \TT{0FFFFFFF0h} записывается как \TT{\$-16}.
Это то же самое: \TT{16} в десятичной системе это \TT{0x10} в шестнадцатеричной.
\TT{-0x10} будет как раз \TT{0xFFFFFFF0} (в рамках 32-битных чисел).

\myindex{x86!\Instructions!MOV}
Возвращаемый результат устанавливается в 0 обычной инструкцией \MOV, а не \XOR.
\MOV просто загружает значение в регистр.
Её название не очень удачное (данные не перемещаются, а копируются). В других архитектурах подобная инструкция обычно носит название \q{LOAD} или \q{STORE} или что-то в этом роде.

